<?php
/**
 * 微信开发平台 第三方接口类
 * File: FwOpen.php
 * User: LiaoJiangYi
 * Time: 2016/5/19 12:39
 * QQ:   527532113
 * WeChat: jyliao_vip
 * Mail: jyliao@vip.qq.com
 */
namespace Ext\WeChat;
class FwOpen extends Fw
{
    const AUTH_URL = '/component/api_component_token';
    const AUTH_CODE_URL = '/component/api_create_preauthcode?';
    const AUTH_INFO_URL = '/component/api_query_auth?';
    const WECHAT_INFO_URL = '/component/api_get_authorizer_info?';
    const WECHAT_ACCESS_TOKEN_REFRESH_URL = '/component/api_authorizer_token?';
    const LOGIN_PAGE = 'https://mp.weixin.qq.com/cgi-bin/componentloginpage?';
    private $_preAuthCode = null;
    private $_wechatAccessToken;
    public function __construct(\Phalcon\Config $options)
    {
        $this->token = $options->token;
        $this->encodingAESKey = $options->encodingAESKey;
        $this->appId = $options->appId;
        $this->appsecret = $options->secret;
        $this->debug = $options->debug;
        $this->logcallback = $options->logcallback;
        $this->cachePrefix = $this->cachePrefix.'_'.$this->appId;
    }
    //获取微信授权码
    public function getComponentVerify()
    {
        return $this->getCache('component_verify_ticket');
    }
    //缓存微信授权码
    public function setRevComponentVerify()
    {
        if (isset($this->_receive['ComponentVerifyTicket']))
            return $this->setCache('component_verify_ticket',$this->_receive['ComponentVerifyTicket']);
        else
            return false;
    }
    //获取第三方平台component_access_token
    public function requestAccessToken()
    {
        return $this->httpRaw(self::API_URL_PREFIX.self::AUTH_URL,array(
            'component_appid' => $this->appId,
            'component_appsecret' => $this->appsecret,
            'component_verify_ticket' => $this->getComponentVerify()
        ));
    }
    /**
     * 设置PreAuthCode
     * @param array $accessToken
     */
    public function setPreAuthCode($result)
    {
        if (!isset($result['pre_auth_code'])) {
            throw new \Phalcon\Exception('The wechat access_token must be set.');
        } elseif(!isset($result['expire'])) {
            throw new \Phalcon\Exception('Wechat access_token expire time must be set.');
        }
        $this->_preAuthCode = $result;
    }
    //获取预授权码pre_auth_code
    public function getPreAuthCode($force = false)
    {
        $time = time(); // 为了更精确控制.取当前时间计算
        if ($this->_preAuthCode === null || $this->_preAuthCode['expire'] < $time || $force) {
            $result = $this->_preAuthCode === null && !$force ? $this->getCache('pre_auth_code', false) : false;
            if ($result === false || (!empty($result['expire']) && $result['expire']<time()-60)) {
                $result = $this->httpRaw(self::API_URL_PREFIX.self::AUTH_CODE_URL.'component_access_token='.$this->getAccessToken(),array(
                    'component_appid' => $this->appId,
                ));
                if (empty($result['pre_auth_code'])) {
                    print_r($result);
                    throw new \Phalcon\Exception('Fail to get pre_auth_code from wechat server.');
                }
                $result['expire'] = $time + $result['expires_in'];
                $this->setCache('pre_auth_code', $result, $result['expires_in']);
            }
            $this->setPreAuthCode($result);
        }
        return $this->_preAuthCode['pre_auth_code'];
    }
    //获取用户授权url页面
    public function getLoginUrl($redirect_uri)
    {
        return self::LOGIN_PAGE.'component_appid='.$this->appId.'&pre_auth_code='.$this->getPreAuthCode().'&redirect_uri='.urlencode($redirect_uri);
    }
    //换取公众号的接口调用凭据和授权信息
    public function getAuthInfo($authorization_code)
    {
        return $this->httpRaw(self::API_URL_PREFIX.self::AUTH_INFO_URL.'component_access_token='.$this->getAccessToken(),array(
            'component_appid' => $this->appId,
            'authorization_code' => $authorization_code
        ));
    }
    //获取公众号基本信息
    public function getWechatInfo($authorizer_appid)
    {
        return $this->httpRaw(self::API_URL_PREFIX.self::WECHAT_INFO_URL.'component_access_token='.$this->getAccessToken(),array(
            'component_appid' => $this->appId,
            'authorizer_appid' => $authorizer_appid
        ));
    }
    /**
     * 设置AccessToken
     * @param array $accessToken
     */
    public function setWechatAccessToken($accessToken)
    {
        if (!isset($accessToken['authorizer_access_token'])) {
            throw new \Phalcon\Exception('The wechat access_token must be set.');
        } elseif(!isset($accessToken['expire'])) {
            throw new \Phalcon\Exception('Wechat access_token expire time must be set.');
        }
        $this->_wechatAccessToken = $accessToken;
    }
    //把授权设置为全局授权 设置为全局后可正常调用服务号的方法 但是开发平带第三方账号方法会失效
    public function setPublicAccessToken($appId)
    {
        $token = $this->getWechatAccessToken($appId);
        return $this->setAccessToken(array(
            'access_token' => $token,
            'expire' => $this->_wechatAccessToken['expire'],
            'expires_in' => $this->_wechatAccessToken['expires_in'],
        ));
    }
    //获取公众号的access_token
    public function getWechatAccessToken($appId,$force = false)
    {
        $cacheName = $appId.'_access_token';
        $time = time();
        if ($this->_wechatAccessToken === null || $this->_wechatAccessToken['expire'] < $time || $force) {
            $result = $this->getCache($cacheName, false);
            if(empty($result['authorizer_refresh_token']))exit('no refresh_access_token');
            if ($result['expire']<time()-60 || $force) {
                $result = $this->refreshWechatAccessToken($appId,$result['authorizer_refresh_token']);
                if (!$result) {
                    throw new \Phalcon\Exception('Fail to get authorizer_access_token from wechat server.');
                }
                $result['expire'] = $time + $result['expires_in'];
                $this->setCache($cacheName, $result, $result['expires_in']);
            }
            $this->setWechatAccessToken($result);
        }
        return $this->_wechatAccessToken['authorizer_access_token'];
    }
    //{"authorizer_access_token":"reE3sjyLQQ_4g7IvVoGBOjFxzsq_y1mIMaYIpNBAPlUFd1eLU3YC2GTvC6qMOSqDQqfICBN3GLVnnhpI0tvM-ww6MFKQNUQgwzAxuzzBi0oLVcesNeqPieXxFEqBG2U1GZGbADDJCJ","expires_in":7200,"authorizer_refresh_token":"refreshtoken@@@eUIyDBhFfDiu8_tk5j_qEXDl2R22UFG84uzAYGoIo-g"}
    //刷新公众号的access_token
    public function refreshWechatAccessToken($appId,$refresh_token)
    {
        $result = $this->httpRaw(self::API_URL_PREFIX.self::WECHAT_ACCESS_TOKEN_REFRESH_URL.'component_access_token='.$this->getAccessToken(),array(
            'component_appid' => $this->appId,
            'authorizer_appid' => $appId,
            'authorizer_refresh_token' => $refresh_token,
        ));
        return $result;
    }
    //获取网页授权登录地址
    const OAUTH_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize';
    public function getOAuthAuthorizeUrl($appId,$url,$state='',$scope='snsapi_userinfo')
    {
        return self::OAUTH_AUTHORIZE_URL.'?appid='.$appId.'&redirect_uri='.urlencode($url).'&response_type=code'.
            '&scope='.$scope.'&state='.$state.'&component_appid='.$this->appId.'#wechat_redirect';
    }
    const OAUTH_ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/component/access_token';
    public function getOAuthAccessToken($appId='',$code=''){
        return $this->httpGet(self::OAUTH_ACCESS_TOKEN_URL,array(
            'appid' => $appId,
            'code' => $code,
            'grant_type' => 'authorization_code',
            'component_appid' => $this->appId,
            'component_access_token' => $this->getAccessToken()
        ));
    }
    const OAUTH_USERINFO_URL = 'https://api.weixin.qq.com/sns/userinfo';
    public function getUserInfo($access_token,$openid=''){
        return $this->httpGet(self::OAUTH_USERINFO_URL,array(
            'access_token' => $access_token,
            'openid' => $openid,
            'lang' => 'zh_CN'
        ));
    }
}